//
// Created by Pulsar on 2019/4/18.
//


#define __Xs ON
#ifdef __Xs
#include <Eigen/Core>
#include <ios>
#include <iostream>
#include <string>
#include <opencv2/opencv.hpp>
#include <opencv2/opencv_modules.hpp>
#include <opencv2/core/eigen.hpp>
#include <opencv2/ml/ml.hpp>
#include <layers/ANNLayer.h>
using namespace cv;
using namespace cv::ml;
using namespace std;
using namespace Eigen;
int main(int argc, char **argv) {
    double learning_rate = 0.01;
    int input_nodes = 4;
    int hidden_nodes = 3;
    int output_nodes = 3;
    AnnLayer model(learning_rate, input_nodes, hidden_nodes, output_nodes);
    cout<<"load train data"<<endl;
    Ptr<ml::TrainData> t_train_data= ml::TrainData::loadFromCSV("E:\\WorkSpace\\TestCode\\LearnDeep\\data\\iris_train_data.csv", 1,0,-1);
    Ptr<ml::TrainData> t_train_label_list= ml::TrainData::loadFromCSV("E:\\WorkSpace\\TestCode\\LearnDeep\\data\\iris_train_data_label.csv", 0,0,-1);
//    Ptr<ml::TrainData> data= ml::TrainData::loadFromCSV("E:\\WorkSpace\\TestCode\\LearnDeep\\data\\mnist\\mnist_train.csv", 1);
//    Ptr<ml::TrainData> data= ml::TrainData::loadFromCSV("E:\\WorkSpace\\TestCode\\LearnDeep\\data\\mnist\\mnist_test.csv", 1);
    Mat cv_train_data = t_train_data->getTrainSamples();
    Mat cv_train_label_list = t_train_label_list->getTrainSamples();
//
    MatrixXd train_data(cv_train_data.rows, cv_train_data.cols);
    MatrixXd train_labels_list(cv_train_label_list.rows,1);
    MatrixXd train_labels(cv_train_label_list.rows,output_nodes);
    train_labels.fill(0);
    cv2eigen(cv_train_data,train_data);
    cv2eigen(cv_train_label_list,train_labels_list);
    cout<<"load train data end"<<endl;


//    cout<<"train_data\n"<<train_data<<endl;
//    cout<<"train_label\n"<<train_labels_list<<endl;
    for(int row=0;row<train_labels_list.rows();row+=1){
        train_labels(row,(int)train_labels_list(row,0))=0.9999;
    }

    model.train(train_data, train_labels, 500);
    cout<<"load test data"<<endl;
//    Ptr<ml::TrainData> ml_data= ml::TrainData::loadFromCSV("E:\\WorkSpace\\TestCode\\LearnDeep\\data\\mnist\\mnist_test.csv", 1);
    Ptr<ml::TrainData> t_test_data= ml::TrainData::loadFromCSV("E:\\WorkSpace\\TestCode\\LearnDeep\\data\\iris_test_data.csv", 1,0,-1);
    Ptr<ml::TrainData> t_test_label= ml::TrainData::loadFromCSV("E:\\WorkSpace\\TestCode\\LearnDeep\\data\\iris_test_data_label.csv", 0,0,-1);
    Mat test_cv_data = t_test_data->getTrainSamples();
    Mat test_cv_label = t_test_label->getTrainSamples();
    MatrixXd test_data(test_cv_data.rows, test_cv_data.cols);
    MatrixXd test_label_list(test_cv_data.rows,1);
    cv2eigen(test_cv_data,test_data);
    cv2eigen(test_cv_label,test_label_list);
    cout<<"end load test data end"<<endl;
    double acc=0.0;
    double pre_true=0;
    double pre_error=0;
    for (int i = 0; i < test_data.rows(); i++) {
        Eigen::MatrixXd output = model.query(train_data.row(i));
//        Eigen::MatrixXd output = model.predict(train_data.row(i));
        double max = 0.0;
        double label = 0;
        for (int j = 0; j < output.rows(); j++) {
            double temp = (double) output(j, 0);
            if (temp > max) {
                max = temp;
                label = j;
            }
        }
        if((int)test_label_list(i,0)==label)
            pre_true+=1;
        else
            pre_error+=1;
        std::cout << " real : " << test_label_list(i,0) << " pre : " <<label<<" out: "<< output.transpose() << std::endl;
    }
    std::cout<<"ACC: "<<(pre_true/test_label_list.rows())<<std::endl;

    getchar();

}
#else
#include <Eigen/Core>
#include <cuda.h>
#include <iostream>

int main()
{
    std::cout << "Hello Eigen\t";
    std::cout << EIGEN_WORLD_VERSION << "." << EIGEN_MAJOR_VERSION << "." << EIGEN_MINOR_VERSION << "\n";
    std::cout << "Hello nvcc\t";
    std::cout << CUDA_VERSION  <<std::endl;
    return 0;
}
#endif

